# coding=utf-8
'''
Created on Jun 15, 2009

@license: License: LGPL
@copyright: (c) 2009, dogsing.cn
@author: ant-man
'''

class MocRuntimeException(Exception): pass

class MocTypeConvertException(MocRuntimeException): pass

class MocOperationInvalid(MocRuntimeException): pass

binary_operator = {
    # Arithmetic operators
    '+'  : 'PLUS',
    '-'  : 'MINUS',
    '*'  : 'TIMES',
    '/'  : 'DIVIDE',
    '%'  : 'MOD',
    '|'  : 'OR',
    '&'  : 'AND',
    '^'  : 'XOR',
    '<<' : 'LSHIFT',
    '>>' : 'RSHIFT',
    # Logical operators
    '||' : 'LOR',
    '&&' : 'LAND',
    '<'  : 'LT',
    '>'  : 'GT',
    '<=' : 'LE',
    '>=' : 'GE',
    '==' : 'EQ',
    '!=' : 'NE',
}

unary_operator = {
    '~'  : 'NOT',
    '!'  : 'LNOT',
    '+'  : 'PREPLUS',
    '-'  : 'PREMINUS',
}

class MocObject(object):
    '''
    Base Class of mocObjects which includes mocConstant, mocCollection
    and mocCallable
    '''
    TYPE = "OBJECT"

    def __init__(self):
        # this is a dictionary contains the field of current object
        # each field is a MocInstance, key is the name of field and
        # the value is the ID of bind instance
        self.__filed = {}

    def binary_op(self, op, lhs, rhs):
        meth = 'op_' + binary_operator[op]
        if hasattr(self, meth) :
            return getattr(self, meth)(lhs, rhs)
        raise MocOperationInvalid('the operation of %s is not supported by %s' % (op, self.__class__.__name__))

    def unary_op(self, op, rhs):
        meth = 'op_' + unary_operator[op]
        if hasattr(self, meth) :
            return getattr(self, meth)(rhs)
        raise MocOperationInvalid('the operation of %s is not supported by %s' % (op, self.__class__.__name__))

    def new_inst(self, value):
        raise NotImplementedError()

    def pyval(self, inst):
        return None

    def equals(self, lhs):
        if isinstance(lhs, MocObject) :
            return self.TYPE == lhs.TYPE
        if isinstance(lhs, str) :
            return self.TYPE == lhs
        return self.TYPE == lhs.type

    def add_object_field(self, filed_map):
        """
        TODO:
        """
        self.__filed.update(filed_map)

    def get_field(self, name):

        return self.__filed.get(name, None)
